package gek.uni.aspirant.ocl.parser.mptree.tree;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

public class Node implements INode {

	/**
	 * Идентификатор
	 */
	private String ID;

	/**
	 * Имя узла
	 */
	private String name;

	private INode parent;

	private Set<INode> children;

	public Node() {
		this("", new HashSet<INode>());
	}

	public Node(String name) {
		this(name, new HashSet<INode>());
	}

	public Node(String name, Set<INode> children) {
		this.name = name;
		this.children = children;
	}

	@Override
	public void setID(String ID) {
		this.ID = ID;
	}

	@Override
	public String getID() {
		return ID;
	}

	@Override
	public Set<INode> getChildren() {
		return children;
	}

	@Override
	public String getName() {
		return name;
	}

	@Override
	public void setChildren(Set<INode> children) {
		this.children = children;
	}

	@Override
	public void setName(String name) {
		this.name = name;
	}

	@Override
	public void addChild(INode newChild) {
		if (newChild == null)
			return;
		if (newChild instanceof RootNode)
			addChildren(newChild.getChildren());
		else if (this.children.contains(newChild)) {
			for (INode myChild : this.children)
				if (myChild.equals(newChild))
					myChild.addChildren(newChild.getChildren());
		} else {
			this.children.add(newChild);
			newChild.setParent(this);
		}
	}

	@Override
	public void addChildren(Collection<INode> newChildren) {
		for (INode node : newChildren) {
			if (node == null)
				continue;
			addChild(node);
		}
	}

	@Override
	public void removeChild(INode child) {
		this.children.remove(child);
	}

	@Override
	public INode getRoot() {
		INode parent = getParent();
		if (parent == null)
			return this;
		while (parent.getParent() != null)
			parent = parent.getParent();
		return parent;
	}

	@Override
	public INode getParent() {
		return parent;
	}

	@Override
	public void setParent(INode parent) {
		this.parent = parent;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Node other = (Node) obj;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

	protected String getShortName(){
	    return name;
	}
	
	@Override
	public String toString() {
		StringBuilder bldr = new StringBuilder();
		bldr.append(getShortName());
		bldr.append("=[");
		for (INode node : children)
			bldr.append(node.toString()).append(";");
		bldr.append("]");
		return bldr.toString();
	}
}
